/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2021-12-10     xu       the first version
 */
#include "http_api_utils.h"

#include "gbk2utf8.h"
#include "webclient.h"

#define DBG_TAG "api.util"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include <rtthread.h>

char* strdup_gbk(const char* str)
{
    char* gbk = RT_NULL;
    if (utf82gbk(&gbk, (void*)str, rt_strlen(str)) < 0) {
        LOG_E("convert to gbk failed!");
        return rt_strdup(str);
    }
    // LOG_D("convert to gbk: %s", gbk);
    return gbk;
}

void copy_string_field(const char** target, cJSON* json, const char* name)
{
    cJSON* field = cJSON_GetObjectItem(json, name);
    if (field) {
        const char* gbk_str = strdup_gbk(field->valuestring);
        LOG_D("Got %s: %s", name, gbk_str);
        *target = gbk_str;
    }
}

int add_string_field(cJSON* json, const char* name, const char* value)
{
    cJSON* val_obj = cJSON_CreateString(value);
    if (!val_obj) {
        return -1;
    }
    return cJSON_AddItemToObject(json, name, val_obj) ? 0 : -1;
}

#define HTTP_HEAD_BUFFER_SIZE 1024
#define HTTP_BODY_BUFFER_SIZE 4096

int http_get(const char* uri, char** response, size_t* resp_len)
{
    struct webclient_session* session = RT_NULL;
    char* buffer = RT_NULL;
    int index, ret = 0;
    int bytes_read, resp_status;
    int content_length = -1;

    RT_ASSERT(response && resp_len);
    *response = RT_NULL;
    *resp_len = 0;

    buffer = (char*)web_malloc(HTTP_BODY_BUFFER_SIZE);
    if (buffer == RT_NULL) {
        LOG_E("no memory for receive buffer.");
        ret = -RT_ENOMEM;
        goto __exit;
    }

    /* create webclient session and set header response size */
    session = webclient_session_create(HTTP_HEAD_BUFFER_SIZE);
    if (session == RT_NULL) {
        ret = -RT_ENOMEM;
        goto __exit;
    }

    /* send GET request by default header */
    if ((resp_status = webclient_get(session, uri)) != 200) {
        LOG_E("webclient GET request failed, response(%d) error.", resp_status);
        ret = -RT_ERROR;
        goto __exit;
    }

    LOG_D("webclient get response data:");
    content_length = webclient_content_length_get(session);
    if (content_length < 0) {
        LOG_D("webclient GET request type is chunked.");
        do {
            bytes_read = webclient_read(session, (void*)buffer, HTTP_BODY_BUFFER_SIZE);
            if (bytes_read <= 0) {
                break;
            }
            *resp_len += bytes_read;
            *response = rt_realloc(*response, *resp_len);
            rt_memcpy(*response, buffer, bytes_read);

            for (index = 0; index < bytes_read; index++) {
                rt_kprintf("%c", buffer[index]);
            }
        } while (1);
        rt_kprintf("\n");
    } else {
        int content_pos = 0;
        do {
            int remain_size = content_length - content_pos;
            int count = remain_size > HTTP_BODY_BUFFER_SIZE ? HTTP_BODY_BUFFER_SIZE : remain_size;
            bytes_read = webclient_read(session, (void*)buffer, count);
            *resp_len += bytes_read;
            *response = rt_realloc(*response, *resp_len);
            rt_memcpy(*response, buffer, bytes_read);
            for (index = 0; index < bytes_read; index++) {
                rt_kprintf("%c", buffer[index]);
            }
            content_pos += bytes_read;
        } while (content_pos < content_length);
        rt_kprintf("\n");
        rt_kprintf("cotent_pos=%d, cotent_length=%d\n", content_pos, content_length);
    }

__exit:
    if (session) {
        webclient_close(session);
    }

    if (buffer) {
        web_free(buffer);
    }
    return ret;
}

extern void at_print_raw_cmd(const char* name, const char* buf, rt_size_t size);

#include <stdlib.h>
static int ramdump(int argc, char* argv[])
{
    if (argc < 3) {
        rt_kprintf("Usage: %s addr size\n", __func__);
        return -1;
    }
    long addr = strtol(argv[1], RT_NULL, 16);
    rt_size_t size = atoi(argv[2]);
    at_print_raw_cmd("addr", (char*)addr, size);
    return 0;
}
MSH_CMD_EXPORT(ramdump, print memory data);